/*
 * Rule.cpp
 *
 *  Created on: May 25, 2011
 *      Author: Stijn, Bart, Dave
 */

#include <iostream>

#include "Token.h"
#include "Rule.h"

Rule::Rule() {
	commands = new std::map<Command*, int>();
	isBackground = false;
	isChildProcess = false;
	childPid = 0;
}

Rule::~Rule() {
	for(std::map<Command*, int>::iterator iterator = commands->begin(); iterator != commands->end(); ++iterator) {
		delete iterator->first;
	}

	commands->erase(commands->begin(), commands->end());
	delete commands;
}

void Rule::addCommand(Command* command, int lastToken) {
	commands->insert(std::pair<Command*, int>(command, lastToken));
}

void Rule::removeLastCommand() {
	std::map<Command*, int>::iterator iterator = --commands->end();
	commands->erase(iterator);
}

Command* Rule::getLastCommand() {
	std::map<Command*, int>::iterator iterator = --commands->end();
	return iterator->first;
}

int Rule::getLastToken() {
	std::map<Command*, int>::iterator iterator = --commands->end();
	return iterator->second;
}

bool Rule::hasCommands() {
	return commands->size() > 0;
}

void Rule::setBackground() {
	isBackground = true;
}

bool Rule::getIsChildProcess() {
	return isChildProcess;
}

bool Rule::getIsBackground(){
	return isBackground;
}

int Rule::getChildPid(){
	return childPid;
}

bool Rule::execute() {
	bool keepProcessAlive = true;
	int executor = -2;
	//if(isBackground) executor = fork();
	//executor = -2: parent process, unforked
	//executor = -1: parent process, fork failed
	//executor =  0: child process for background
	//executor >  0: parent process, forked

	if(executor == 0 || executor == -2) {
		for(std::map<Command*, int>::iterator iterator = commands->begin(); iterator != commands->end(); ++iterator) {
			Command* command = iterator->first;
			command->setBackground(isBackground);
			if(iterator->second == -1) { // First command, no token
				keepProcessAlive = command->runCommand();
			} else {
				if(iterator->second == Token::AND) {
					//if(WIFEXITED(lastCommandStatus)) { // Last didn't fail, so execute this one
						keepProcessAlive = command->runCommand();
					//}
				} else if(iterator->second == Token::OR) {
					//if(!WIFEXITED(lastCommandStatus)) { // Last command failed, so execute this one
					keepProcessAlive = command->runCommand();
					//}
				}
			}
			childPid = command->getChildPid();
		}
		if(executor == 0) isChildProcess = true;//exit(EXIT_SUCCESS);
	} else if(executor == -1) std::cout << "Fork Failed!" << std::endl;
	else if(executor > 0)		childPid = executor;
	return keepProcessAlive;
}
